package com.zenithmind.user.config;

import com.zenithmind.common.security.CustomJwtAuthenticationConverter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.RequestMatcher;

/**
 * 改进的安全配置类
 * 遵循单一职责原则：专门负责Spring Security配置
 * 遵循开闭原则：通过配置属性支持不同的安全策略
 * 遵循依赖倒置原则：依赖UserSecurityProperties抽象配置
 */
@Slf4j
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(prePostEnabled = true)
@RequiredArgsConstructor
@ConditionalOnProperty(prefix = "zenithmind.user.security", name = "enabled", havingValue = "true", matchIfMissing = true)
public class ImprovedSecurityConfig {

    private final UserSecurityProperties userSecurityProperties;

    /**
     * 主要安全过滤链配置
     * 遵循配置优于约定的原则，通过SecurityProperties进行配置
     */
    @Bean
    @Order(2)
    public SecurityFilterChain defaultSecurityFilterChain(
            HttpSecurity http, 
            RequestMatcher oauth2EndpointsMatcher) throws Exception {
        
        log.info("配置用户服务安全过滤链");
        
        http
            // 排除OAuth2授权服务器端点
            .securityMatcher(request -> !oauth2EndpointsMatcher.matches(request))
            // 禁用CSRF保护（API服务通常不需要）
            .csrf(AbstractHttpConfigurer::disable)
            // 配置授权规则
            .authorizeHttpRequests(this::configureAuthorization)
            // 配置会话管理
            .sessionManagement(this::configureSessionManagement)
            // 配置OAuth2资源服务器
            .oauth2ResourceServer(this::configureOAuth2ResourceServer);
        
        log.info("用户服务安全配置完成");
        return http.build();
    }

    /**
     * 配置授权规则
     * 遵循开闭原则：通过配置文件扩展授权规则
     */
    private void configureAuthorization(
            org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry authorize) {
        
        // 公开访问路径
        String[] publicPaths = userSecurityProperties.getAllPublicPaths();
        if (publicPaths.length > 0) {
            authorize.requestMatchers(publicPaths).permitAll();
            log.debug("配置公开路径: {}", java.util.Arrays.toString(publicPaths));
        }
        
        // 用户角色路径
        String[] userPaths = userSecurityProperties.getUserPaths();
        if (userPaths.length > 0) {
            authorize.requestMatchers(userPaths).authenticated();
            log.debug("配置用户路径: {}", java.util.Arrays.toString(userPaths));
        }
        
        // 管理员角色路径
        String[] adminPaths = userSecurityProperties.getAdminPaths();
        if (adminPaths.length > 0) {
            authorize.requestMatchers(adminPaths).hasAnyAuthority("ADMIN", "ROLE_ADMIN", "SUPER_ADMIN", "ROLE_SUPER_ADMIN");
            log.debug("配置管理员路径: {}", java.util.Arrays.toString(adminPaths));
        }
        
        // 超级管理员路径
        String[] superAdminPaths = userSecurityProperties.getSuperAdminPaths();
        if (superAdminPaths.length > 0) {
            authorize.requestMatchers(superAdminPaths).hasAnyAuthority("SUPER_ADMIN", "ROLE_SUPER_ADMIN");
            log.debug("配置超级管理员路径: {}", java.util.Arrays.toString(superAdminPaths));
        }
        
        // 其他请求需要认证
        if (userSecurityProperties.isStrictMode()) {
            authorize.anyRequest().authenticated();
            log.debug("启用严格模式：所有其他请求需要认证");
        } else {
            authorize.anyRequest().permitAll();
            log.debug("非严格模式：允许所有其他请求");
        }
    }

    /**
     * 配置会话管理
     * 遵循单一职责原则：专门处理会话相关配置
     */
    private void configureSessionManagement(
            org.springframework.security.config.annotation.web.configurers.SessionManagementConfigurer<HttpSecurity> session) {
        
        session.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        
        UserSecurityProperties.AuthConfig authConfig = userSecurityProperties.getAuth();
        if (authConfig.getMaxSessions() > 0) {
            session.maximumSessions(authConfig.getMaxSessions())
                   .maxSessionsPreventsLogin(false);
        }
        
        log.debug("配置会话管理：无状态会话，最大会话数: {}", authConfig.getMaxSessions());
    }

    /**
     * 配置OAuth2资源服务器
     * 遵循依赖倒置原则：使用自定义的JWT认证转换器
     */
    private void configureOAuth2ResourceServer(
            org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer<HttpSecurity> oauth2) {
        
        oauth2.jwt(jwt -> {
            jwt.jwtAuthenticationConverter(new CustomJwtAuthenticationConverter());
            log.debug("配置JWT认证转换器");
        });
    }

    /**
     * 安全配置验证Bean
     * 在应用启动时验证配置的正确性
     */
    @Bean
    public SecurityConfigValidator securityConfigValidator() {
        return new SecurityConfigValidator(userSecurityProperties);
    }

    /**
     * 安全配置验证器
     * 遵循单一职责原则：专门负责配置验证
     */
    public static class SecurityConfigValidator {
        private final UserSecurityProperties userSecurityProperties;

        public SecurityConfigValidator(UserSecurityProperties userSecurityProperties) {
            this.userSecurityProperties = userSecurityProperties;
            validateConfiguration();
        }

        private void validateConfiguration() {
            log.info("验证用户服务安全配置...");

            // 验证JWT配置
            UserSecurityProperties.JwtConfig jwtConfig = userSecurityProperties.getJwt();
            if (jwtConfig.getAccessTokenExpiration() <= 0) {
                throw new IllegalArgumentException("访问令牌过期时间必须大于0");
            }
            if (jwtConfig.getRefreshTokenExpiration() <= jwtConfig.getAccessTokenExpiration()) {
                log.warn("刷新令牌过期时间应该大于访问令牌过期时间");
            }

            // 验证路径配置
            UserSecurityProperties.PathConfig pathConfig = userSecurityProperties.getPaths();
            if (pathConfig.getPublicPaths().isEmpty()) {
                log.warn("没有配置公开路径，可能导致所有请求都需要认证");
            }

            // 验证认证配置
            UserSecurityProperties.AuthConfig authConfig = userSecurityProperties.getAuth();
            if (authConfig.getMaxRetryAttempts() <= 0) {
                throw new IllegalArgumentException("最大重试次数必须大于0");
            }
            if (authConfig.getLockoutDuration() <= 0) {
                throw new IllegalArgumentException("锁定时间必须大于0");
            }

            log.info("用户服务安全配置验证通过");
        }
    }
}
